package org.linphone.call;

import android.Manifest;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.compatibility.Compatibility;
import org.linphone.core.Address;
import org.linphone.core.AddressFamily;
import org.linphone.core.Call;
import org.linphone.core.Call.State;
import org.linphone.core.CallListenerStub;
import org.linphone.core.CallParams;
import org.linphone.core.CallStats;
import org.linphone.core.ChatMessage;
import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub;
import org.linphone.core.PayloadType;
import org.linphone.core.Player;
import org.linphone.core.Reason;
import org.linphone.core.StreamType;
import org.linphone.core.tools.Log;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneHelper;
import org.linphone.utils.LinphoneUtils;

import java.text.DecimalFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


public class CallActivity extends AppCompatActivity implements OnClickListener {

    private static CallActivity sInstance;
    //切换摄像头
    private ImageView mSwitchCamera,mAddUser;
    //通话时长，对方称呼和头像
    private RelativeLayout mActiveCallHeader, mAvatarLayout;
    //挂断、静音、扩音
    private ImageView mHangUp, mMicro, mSpeaker;
    //语音fragment
    private CallAudioFragment mAudioCallFragment;
    //视频fragment
    private CallVideoFragment mVideoCallFragment;
    //是否是扩音或静音
    private boolean mIsSpeakerEnabled = false, mIsMicMuted = false;
    //摄像头数量
    private int mCameraNumber;
    //核心回调
    private CoreListenerStub mListener;
    //通话时长控件
    private Chronometer timer;
    private TextView contactName;
    public static CallActivity instance() {
        return sInstance;
    }

    public static boolean isInstanciated() {
        return sInstance != null;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sInstance = this;

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        Compatibility.setShowWhenLocked(this, true);
        setContentView(R.layout.call);

        mCameraNumber = AndroidCameraConfiguration.retrieveCameras().length;

        mListener = new CoreListenerStub() {
            @Override
            public void onCallStateChanged(
                    Core lc, final Call call, Call.State state, String message) {


                if (state == State.IncomingReceived || state == State.IncomingEarlyMedia) {
                    // This scenario will be handled by the Service listener
                    call.decline(Reason.Busy);
                    return;
                }
                if (Call.State.End == state) {
                    //对方挂断电话
                    if (!LinphoneHelper.getInstance().isTalk(call)) {
                        finish();
                    }
                }
            }
        };
        //初始化view
        initUI();
        mIsSpeakerEnabled = LinphoneManager.getInstance().isSpeakerEnabled();
        mIsMicMuted = !LinphoneManager.getLc().micEnabled();
        //根据
        Fragment callFragment;
        Call currentCall = LinphoneManager.getLc().getCurrentCall();
        if(currentCall == null){
            finish();
            return;
        }
        if (isVideoEnabled(currentCall)) {
            callFragment = new CallVideoFragment();
            mVideoCallFragment = (CallVideoFragment) callFragment;
            displayVideoCall(true);
            LinphoneManager.getInstance().routeAudioToSpeaker();
            mIsSpeakerEnabled = true;

            switchVideo();
        } else {
            callFragment = new CallAudioFragment();
            mAudioCallFragment = (CallAudioFragment) callFragment;
            displayVideoCall(false);
        }

        callFragment.setArguments(getIntent().getExtras());
        getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.fragmentContainer, callFragment)
                .commitAllowingStateLoss();

    }

    private boolean isVideoEnabled(Call call) {
        boolean isVideoEnable = false;
        if (call.getParams().videoEnabled() || call.getRemoteParams().videoEnabled() || call.getCurrentParams().videoEnabled()) {
            isVideoEnable = true;
        }
        return isVideoEnable;
    }


    private void initUI() {

        timer = findViewById(R.id.current_call_timer);
        mHangUp = findViewById(R.id.hang_up);
        mHangUp.setOnClickListener(this);


        mMicro = findViewById(R.id.micro);
        mMicro.setOnClickListener(this);

        mSpeaker = findViewById(R.id.speaker);
        mSpeaker.setOnClickListener(this);

        mActiveCallHeader = findViewById(R.id.active_call);

        mAvatarLayout = findViewById(R.id.avatar_layout);

        mSwitchCamera = findViewById(R.id.switchCamera);
        mSwitchCamera.setOnClickListener(this);

        mAddUser = findViewById(R.id.add_user);
        mAddUser.setOnClickListener(this);

        contactName = findViewById(R.id.current_contact_name);

        mSpeaker.setVisibility(View.VISIBLE);
        LinphoneManager.getInstance().changeStatusToOnThePhone();
    }

    private void refreshIncallUi() {
        refreshInCallActions();
        mMicro.setEnabled(true);
        mSpeaker.setEnabled(true);
        displayCurrentCall(LinphoneManager.getLc().getCurrentCall());
    }

    /**
     * 静音和扩音
     */
    public void refreshInCallActions() {
        mSpeaker.setSelected(mIsSpeakerEnabled);

        if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName())
                != PackageManager.PERMISSION_GRANTED) {
            mIsMicMuted = true;
        }
        mMicro.setSelected(mIsMicMuted);
    }


    @Override
    public void onClick(View v) {
        int id = v.getId();

        if (id == R.id.add_user) {
            addUser();
        } else if (id == R.id.micro) {
            toggleMicro();
        } else if (id == R.id.speaker) {
            toggleSpeaker();
        } else if (id == R.id.hang_up) {
            hangUp();
        } else if (id == R.id.switchCamera) {
            if (mVideoCallFragment != null) {
                mVideoCallFragment.switchCamera();
            }
        }
    }

    private void displayCustomToast(final String message, final int duration) {
        Toast.makeText(this, message, duration).show();
    }

    private void switchVideo() {
        final Call call = LinphoneManager.getLc().getCurrentCall();
        if (call == null) {
            return;
        }

        // Check if the call is not terminated
        if (call.getState() == State.End || call.getState() == State.Released) return;
        {
            if (!call.getRemoteParams().lowBandwidthEnabled()) {
                LinphoneManager.getInstance().addVideo();
            } else {
                displayCustomToast(getString(R.string.error_low_bandwidth), Toast.LENGTH_LONG);
            }
        }
    }

    private void addUser(){

    }

    private void toggleMicro() {
        Core lc = LinphoneManager.getLc();
        mIsMicMuted = !mIsMicMuted;
        lc.enableMic(!mIsMicMuted);
        mMicro.setSelected(mIsMicMuted);
    }

    private void toggleSpeaker() {
        mIsSpeakerEnabled = !mIsSpeakerEnabled;
        if (LinphoneManager.getLc().getCurrentCall() != null) {
            if (isVideoEnabled(LinphoneManager.getLc().getCurrentCall()))
                LinphoneManager.getInstance().enableProximitySensing(false);
            else LinphoneManager.getInstance().enableProximitySensing(!mIsSpeakerEnabled);
        }
        mSpeaker.setSelected(mIsSpeakerEnabled);
        if (mIsSpeakerEnabled) {
            LinphoneManager.getInstance().routeAudioToSpeaker();
            LinphoneManager.getInstance().enableSpeaker(mIsSpeakerEnabled);
        } else {
            Log.d("Toggle mSpeaker off, routing back to earpiece");
            LinphoneManager.getInstance().routeAudioToReceiver();
        }
    }

    private void hangUp() {
        Core lc = LinphoneManager.getLc();
        Call currentCall = lc.getCurrentCall();
        if (currentCall != null) {
            lc.terminateCall(currentCall);
        }
        finish();
    }

    private void displayVideoCall(boolean display) {

        if (display) {
            mActiveCallHeader.setVisibility(View.VISIBLE);
            mAvatarLayout.setVisibility(View.GONE);
            if (mCameraNumber > 1) {
                mSwitchCamera.setVisibility(View.VISIBLE);
            }
            mAddUser.setVisibility(View.VISIBLE);
            contactName.setVisibility(View.GONE);

            setImageSrc(mAddUser,R.drawable.add_user_white);
            setImageSrc(mMicro,R.drawable.micro_white);
            setImageSrc(mSpeaker,R.drawable.speaker_white);
            setImageSrc(mSwitchCamera,R.drawable.camera_white);

        } else {
            mActiveCallHeader.setVisibility(View.VISIBLE);
            mAvatarLayout.setVisibility(View.VISIBLE);
            mSwitchCamera.setVisibility(View.GONE);
            mAddUser.setVisibility(View.GONE);
            contactName.setVisibility(View.VISIBLE);
            setImageSrc(mAddUser,R.drawable.add_user);
            setImageSrc(mMicro,R.drawable.micro);
            setImageSrc(mSpeaker,R.drawable.speaker);
            setImageSrc(mSwitchCamera,R.drawable.camera);
        }
    }

    private void setImageSrc(ImageView imageView,int src){

        imageView.setImageResource(src);
    }

    @Override
    protected void onResume() {
        sInstance = this;
        super.onResume();
        Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
        if (lc != null) {
            lc.addListener(mListener);
        }
        mIsSpeakerEnabled = LinphoneManager.getInstance().isSpeakerEnabled();
        refreshIncallUi();
        handleViewIntent();
    }

    private void handleViewIntent() {
        Intent intent = getIntent();
        if (intent != null && "android.intent.action.VIEW".equals(intent.getAction())) {
            Call call = LinphoneManager.getLc().getCurrentCall();
            if (call != null && isVideoEnabled(call)) {
                Player player = call.getPlayer();
                String path = intent.getData().getPath();
                Log.i("Openning " + path);

                player.open(path);
                Log.i("Start playing");
                player.start();

            }
        }
    }

    @Override
    protected void onPause() {
        Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
        if (lc != null) {
            lc.removeListener(mListener);
        }
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        LinphoneManager.getInstance().changeStatusToOnline();
        LinphoneManager.getInstance().enableProximitySensing(false);
        unbindDrawables(findViewById(R.id.topLayout));

        sInstance = null;
        super.onDestroy();
        System.gc();
    }

    private void unbindDrawables(View view) {
        if (view.getBackground() != null) {
            view.getBackground().setCallback(null);
        }
        if (view instanceof ImageView) {
            view.setOnClickListener(null);
        }
        if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
            ((ViewGroup) view).removeAllViews();
        }
    }


    public void bindAudioFragment(CallAudioFragment fragment) {
        mAudioCallFragment = fragment;
    }

    public void bindVideoFragment(CallVideoFragment fragment) {
        mVideoCallFragment = fragment;
    }

    /**
     * 显示称呼和通话时长
     *
     * @param call
     */
    private void displayCurrentCall(Call call) {
        if(call == null){
            return;
        }
        Address lAddress = call.getRemoteAddress();
        contactName.setText(lAddress.getUsername());
        timer.setBase(SystemClock.elapsedRealtime() - 1000 * call.getDuration());
        timer.start();
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (LinphoneManager.isInstanciated()
                && (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)) {
            LinphoneManager.getLc().terminateCall(LinphoneManager.getLc().getCurrentCall());
            finish();
        }
        return super.onKeyDown(keyCode, event);
    }
}
